package com.sprouting.ops.service;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sprouting.ops.dao.*;
import com.sprouting.ops.model.*;
import com.sprouting.ops.model.qo.AvailableDependQo;
import com.sprouting.ops.model.qo.OpsComponentComputerServerQo;
import com.sprouting.ops.model.qo.OpsComponentQo;
import com.sprouting.ops.model.vo.*;
import com.sprouting.ops.utils.EntityTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (组件信息)表服务实现类
 *
 * @author longx
 * @since 2023-11-20 22:49:09
 */
@Service
@Slf4j
public class OpsComponentService extends ServiceImpl<OpsComponentDao, OpsComponent> {

    @Resource
    private OpsComponentDao opsComponentDao;
    @Resource
    private DromaraFileStorageDao dromaraFileStorageDao;
    @Resource
    private OpsProductDependDao opsProductDependDao;
    @Resource
    private OpsDeployDao opsDeployDao;
    @Resource
    private OpsComponentVersionDao opsComponentVersionDao;
    @Resource
    private OpsCommonUseDao opsCommonUseDao;


    /**
     * 根据名称查询并过滤指定id
     * @param name 组件名称
     * @param id 过滤的id
     * @return
     */
    public OpsComponent getByNameFilterId(String name, String id) {
        return opsComponentDao.getByNameFilterId(name, id);
    }

    /**
     * 分页查询
     * @param page 分页参数
     * @param query 查询参数
     * @return
     */
    public Page<OpsComponentVo> getOpsComponentPageList(Page page, OpsComponentQo query) {
        return opsComponentDao.getOpsComponentPageList(page, query);
    }

    /**
     * 保存组件
     * @param opsComponent 组件信息
     * @param opsUploadFile 组件的图片信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOpsComponent(OpsComponent opsComponent, DromaraFileStorage opsUploadFile) {
        opsComponentDao.insert(opsComponent);
        if (opsUploadFile != null){
            dromaraFileStorageDao.updateById(opsUploadFile);
        }
    }

    /**
     * 更新组件
     * @param opsComponent 组件信息
     * @param uploadFileArray 数组下标0， 新的  数组下标1 旧的文件
     */
    @Transactional(rollbackFor = Exception.class)
    public void updOpsComponent(OpsComponent opsComponent, DromaraFileStorage[] uploadFileArray) {
        opsComponentDao.updateById(opsComponent);

        if (uploadFileArray[0] != null){
            // 新的
            dromaraFileStorageDao.updateById(uploadFileArray[0]);
        }
        if (uploadFileArray[1] != null){
            // 旧的文件
            dromaraFileStorageDao.updateById(uploadFileArray[1]);
        }
    }

    /**
     * 删除组件
     * @param opsComponent 组件信息
     * @param opsUploadFile 图片信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void delOpsComponent(OpsComponent opsComponent, DromaraFileStorage opsUploadFile) {
        opsComponentDao.deleteById(opsComponent);

        if (opsUploadFile != null){
            dromaraFileStorageDao.updateById(opsUploadFile);
        }

        // 删除绑定关系
        LambdaUpdateWrapper<OpsProductDepend> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(OpsProductDepend::getBindId, opsComponent.getId());
        opsProductDependDao.delete(wrapper);

        // 常用文件和文件夹
        LambdaUpdateWrapper<OpsCommonUse> wrapperCommonUse = new LambdaUpdateWrapper<>();
        wrapperCommonUse.eq(OpsCommonUse::getBindId, opsComponent.getId());
        opsCommonUseDao.delete(wrapperCommonUse);

        // 删除版本
        LambdaUpdateWrapper<OpsComponentVersion> wrapperComponentVersion = new LambdaUpdateWrapper<>();
        wrapperComponentVersion.eq(OpsComponentVersion::getComponentId, opsComponent.getId());
        opsComponentVersionDao.delete(wrapperComponentVersion);
    }

    /**
     * 获取可绑定的组件
     * @return
     */
    public List<OpsComponent> getBindableComponent() {
        return opsComponentDao.getBindableComponent();
    }

    /**
     * 查询产品可选依赖-组件
     * @param excludeList 排除的组件ID
     * @param query 查询参数
     * @return
     */
    public Page<AvailableDependVo> getAvailableDepend(Page page, List<String> excludeList, AvailableDependQo query) {
        return opsComponentDao.getAvailableDepend(page, excludeList, query);
    }

    /**
     * 根据id批量查询组件
     * @param idList 主键
     * @return
     */
    public List<OpsComponentVo> getByIdList(List<String> idList) {
        return opsComponentDao.getByIdList(idList);
    }

    /**
     * 根据计算机id查询组件信息
     * @param query 查询参数
     * @return
     */
    public Page<ComponentComputerVo> getComponentByComputerId(Page page, OpsComponentComputerServerQo query) {
        Page<ComponentComputerVo> computerVoPage = opsComponentDao.getComponentByComputerId(page, query);
        List<ComponentComputerVo> list = computerVoPage.getRecords();
        if (CollUtil.isEmpty(list)){
            return computerVoPage;
        }

        // 添加部署信息
        List<String> deployIdList = list.stream().map(ComponentComputerVo::getDeployId).collect(Collectors.toList());
        List<OpsDeploy> deployList = opsDeployDao.selectByIds(deployIdList);
        Map<String, OpsDeploy> map = EntityTool.toMap(deployList, OpsDeploy::getId);

        // 版本信息
        List<String> versionIdList = list.stream().map(ComponentComputerVo::getComponentVersionId).collect(Collectors.toList());
        List<OpsComponentVersion> versionList = opsComponentVersionDao.selectByIds(versionIdList);
        Map<String, OpsComponentVersion> mapVersion = EntityTool.toMap(versionList, OpsComponentVersion::getId);

        for (ComponentComputerVo computerVo : list) {
            // 部署信息
            computerVo.setOpsDeploy(map.get(computerVo.getDeployId()));
            // 版本信息
            computerVo.setOpsComponentVersion(mapVersion.get(computerVo.getComponentVersionId()));
        }

        return computerVoPage;
    }

    /**
     * 根据产品id查询组件
     * @param productId 产品id
     * @return
     */
    public List<OpsComponentVo> getComponentByProductId(String productId) {
        return opsComponentVersionDao.getComponentByProductId(productId);
    }
}

